package cn.sh.ideal.yedis.builder;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;

public abstract class BaseBuilder<T> {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	protected final static String SEPERATOR_NODE = ";";
	protected final static String SEPERATOR_IP_PROT = ":";
	protected static final Lock LOCK = new ReentrantLock();
	/**
	 * 连接池
	 */
	protected T pool;
	/**
	 * 连接池配置
	 */
	protected JedisPoolConfig poolConfig;
	
	/**
	 * 节点信息
	 */
	protected String nodeStr;
	
	/**
	 * 密码
	 */
	protected String password;
	/**
	 * 连接超时时间 单位毫秒
	 */
	protected int timeout =  Protocol.DEFAULT_TIMEOUT;
	
	/**
	 * 读写超时时间 单位毫秒
	 */
	protected int soTimeout = Protocol.DEFAULT_TIMEOUT;
	
	/**
	 * 构建
	 * @return
	 */
	public abstract T build();
	
	/**
	 * 初始化
	 */
	public Object init() {
		if(poolConfig == null) {
			createDefaultPool();
		}
		
		return build();
	}
	
	/**
	 * 初始化默认连接池
	 */
	private void createDefaultPool() {
		poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);
		poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);
		poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE);
		poolConfig.setMinEvictableIdleTimeMillis(60000);
		poolConfig.setTimeBetweenEvictionRunsMillis(30000);
		//JedisPool.borrowObject最大等待时间
		poolConfig.setMaxWaitMillis(1000L);
		poolConfig.setJmxNamePrefix("jedis-pool");
		poolConfig.setJmxEnabled(true);
	}
	
	/**
	 * 配置
	 *
	 * @param poolConfig
	 * @return
	 */
	public BaseBuilder<T> setPoolConfig(JedisPoolConfig poolConfig) {
		this.poolConfig = poolConfig;
		return this;
	}

	public BaseBuilder<T> setPassword(String password) {
		this.password = password;
		return this;
	}
	
	public BaseBuilder<T> setTimeout(int timeout) {
		this.timeout = timeout;
		return this;
	}

	public void setNodeStr(String nodeStr) {
		this.nodeStr = nodeStr;
	}

	public void setSoTimeout(int soTimeout) {
		this.soTimeout = soTimeout;
	}
}
